package club.baimahu.pencil.domain.session;


import club.baimahu.pencil.domain.entity.account.AccountManager;
import club.baimahu.pencil.domain.entity.event.ShortOfStockEventListener;
import club.baimahu.pencil.domain.entity.event.StockShortOfEvent;
import club.baimahu.pencil.exception.StockException;
import club.baimahu.pencil.domain.entity.event.SimpleStockEventMulticaster;
import club.baimahu.pencil.domain.entity.event.StockEventMulticaster;
import club.baimahu.pencil.domain.entity.Goods;
import club.baimahu.pencil.domain.entity.Supplier;
import club.baimahu.pencil.domain.entity.VirtualSupplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class SimpleGoodFactory implements GoodsFactory {


    Logger logger = LoggerFactory.getLogger(SimpleGoodFactory.class);

    StockEventMulticaster stockEventMulticaster = new SimpleStockEventMulticaster();

    AccountManager accountManager;

    Map<String,GoodsStock> goodsStockMap = new ConcurrentHashMap<>();

    Supplier supplier = new VirtualSupplier();

    {
        // 初始化三种商品
        Goods goods1 = new Goods("NO001","双汇火腿肠",new BigDecimal("2"),new BigDecimal(5));
        GoodsStock goodsStock1 = new GoodsStock(goods1,10);

        Goods goods2 = new Goods("NO002","云南白药牙膏100g",new BigDecimal("20"),new BigDecimal(25));
        GoodsStock goodsStock2 = new GoodsStock(goods2,20);

        Goods goods3 = new Goods("NO003","塑料杯",new BigDecimal("1"),new BigDecimal(3));
        GoodsStock goodsStock3 = new GoodsStock(goods3,30);

        goodsStockMap.put(goodsStock1.getGoods().getGoodsNo(),goodsStock1);
        goodsStockMap.put(goodsStock2.getGoods().getGoodsNo(),goodsStock2);
        goodsStockMap.put(goodsStock3.getGoods().getGoodsNo(),goodsStock3);

        stockEventMulticaster.addListener(new ShortOfStockEventListener());
    }

    public SimpleGoodFactory( ){
    }

    public Map<String,GoodsStock> getGoodsStockMap(){
        return this.goodsStockMap;
    }

    public SimpleGoodFactory(AccountManager accountManager){
        this.accountManager = accountManager;
/*        this.accountManager = new AccountManager(this);
        this.accountManager.addCashAccount(bigDecimal);*/
    }


/*    @Override
    public void buyGoods(List<Goods> goodsList) {
        synchronized (accountManager){
            goodsList.stream().forEach(x->{
                accountManager.pay(x.getFactoryPrice());
                GoodsStock goodsStock = goodsStockMap.get(x.getGoodsNo());

                if(goodsStock == null){
                    goodsStock = new GoodsStock(x,1);
                    goodsStockMap.put(x.getGoodsNo(),goodsStock);
                }else{
                    goodsStock.addAmount(1);
                }
            });
        }
    }*/

    private void publishEvent(Replenishment replenishment){
        stockEventMulticaster.multicastEvent(new StockShortOfEvent(replenishment));
    }

    public void replenishIfShortOf(GoodsStock goodsStock){
        if(isShortOf(goodsStock)){
            publishEvent(new Replenishment(goodsStock,accountManager));
        }
    }

    public static boolean isShortOf(GoodsStock goodsStock){
        return goodsStock.getAtomicAmount().doubleValue() < goodsStock.getMinAmount();
    }

    @Override
    public boolean checkoutGoods(List<Goods> goodsList) {

        for(Goods goods : goodsList){
            if(!isAvailable(goods.getGoodsNo(),1)){
                throw new StockException("出库异常，编号为{"+goods.getGoodsNo()+"}的商品没有库存");
            }
            GoodsStock goodsStock = goodsStockMap.get(goods.getGoodsNo());
            goodsStock.reduceAmount(1);
            replenishIfShortOf(goodsStock);
            logger.info("出库编号为{}的商品1件",goods.getGoodsNo());
        }
        return true; 

    }

    @Override
    public Goods getGoods(String goodsNo, Integer amount) {
        GoodsStock  goodsStock =  this.goodsStockMap.get(goodsNo) ;
        if(goodsStock == null){
            return null;
        }
        return goodsStock.getGoods();
    }

    @Override
    public boolean isAvailable(String goodsNo, Integer amount) {
        GoodsStock  goodsStock =  this.goodsStockMap.get(goodsNo) ;
        return goodsStock.getGoods() != null && goodsStock.getAmount() >= amount ;
    }

    @Override
    public void setAccountManager(AccountManager accountManager) {
        this.accountManager = accountManager;
    }

    @Override
    public void stockWithGoods(List<GoodsStock> goodsStockList) {
        synchronized (accountManager){
            goodsStockList.stream().forEach(x->{
                Goods goods = x.getGoods();
                accountManager.pay(goods.getFactoryPrice().multiply(new BigDecimal(x.getAmount())),getSupplier());
                GoodsStock goodsStock = goodsStockMap.get(goods.getGoodsNo());

                if(goodsStock == null){
                    goodsStockMap.put(goods.getGoodsNo(),x);
                }else{
                    goodsStock.addAmount(x.getAmount());
                }
                logger.info("入库编号为【{}】的商品{}件",goods.getGoodsNo(),x.getAmount());
            });
        }
    }

    @Override
    public Supplier getSupplier() {
        return this.supplier;
    }
}
